package com.ktwlsoft.archivemanage.domain.business.businessService.study;

import com.alibaba.fastjson.JSONObject;
import com.ktwlsoft.archivemanage.config.FileStorageProperties;
import com.ktwlsoft.archivemanage.domain.business.businessService.FileService;
import com.ktwlsoft.archivemanage.domain.business.repositoryService.study.StudyKnowledgeRepositoryService;
import com.ktwlsoft.archivemanage.domain.dao.entity.Account;
import com.ktwlsoft.archivemanage.domain.dao.entity.study.StudyKnowledge;
import com.ktwlsoft.archivemanage.payload.Result;
import com.ktwlsoft.archivemanage.payload.ResultType;
import com.ktwlsoft.archivemanage.payload.TemFileResult;
import com.ktwlsoft.archivemanage.payload.exception.BusinessException;
import com.ktwlsoft.archivemanage.service.security.UserPrincipal;
import com.ktwlsoft.archivemanage.service.utils.FileUtils;
import com.ktwlsoft.archivemanage.service.utils.ZipUtils;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

@Service
public class StudyKnowledgeService {

    private final StudyKnowledgeRepositoryService repositoryService;

    private final FileStorageProperties fileStorageProperties;

    private final FileService fileService;

    public StudyKnowledgeService(StudyKnowledgeRepositoryService repositoryService,
                                 FileStorageProperties fileStorageProperties, FileService fileService) {
        this.repositoryService = repositoryService;
        this.fileStorageProperties = fileStorageProperties;
        this.fileService = fileService;
    }

    /**
     * 子系统知识库列表 on 2019/12/30 10:16
     *
     * @param keyWords keyWords
     * @param parentId parentId
     * @param type     type
     * @return Result<?>
     */
    public Result<?> list(int pn, int pageSize, String keyWords, Long parentId, String type) {
        JSONObject object = new JSONObject();
        object.put("keyWords", keyWords != null ? keyWords : "");
        object.put("parentId", parentId != null ? parentId : 0);
        object.put("type", type);
        return Result.ok(repositoryService.findPage(pn, pageSize, object));
    }

    /**
     * 文件预览 on 2019/12/30 10:23
     *
     * @param fileName fileName
     * @return Result<?>
     */
    public ResponseEntity<?> view(String fileName, HttpServletRequest request) {
        List<StudyKnowledge> list = repositoryService.getStudyKnowledgeMapper().getByName(fileName);
        if (list == null || list.size() <= 0) {
            return ResponseEntity.ok(Result.body(null, ResultType.CHECK_ERROR).withMessage("该文件不存在"));
        }
        StudyKnowledge knowledge = list.get(0);
        UrlResource urlResource = null;
        String contentType = null;
        try {
            Path path = Paths.get(knowledge.getUrl()).toAbsolutePath().normalize();
            urlResource = new UrlResource(path.toUri());
            if (!urlResource.exists()) {
                return ResponseEntity.ok(Result.body(null, ResultType.CHECK_ERROR).withMessage("获取不到该文件"));
            }
            contentType = request.getServletContext().getMimeType(urlResource.getFile().getAbsolutePath());
        } catch (IOException e) {
            e.printStackTrace();
            return ResponseEntity.ok(Result.body(null, ResultType.BUSINESS_SUCCESS));
        }
        if (contentType == null) {
            contentType = "application/octet-stream";
        }
        return ResponseEntity.ok().contentType(MediaType.parseMediaType(contentType)).body(urlResource);
    }

    /**
     * 删除文件 on 2019/12/30 12:14
     *
     * @param fileName fileName
     * @return Result<?>
     */
    @Transactional(rollbackFor = Exception.class)
    public Result<?> delete(String fileName) {
        List<StudyKnowledge> list = repositoryService.getStudyKnowledgeMapper().getByName(fileName);
        if (list == null || list.size() <= 0) {
            return Result.body(null, ResultType.CHECK_ERROR).withMessage("该数据不存在");
        }
        for (StudyKnowledge knowledge : list) {
            if ("FO".equals(knowledge.getFormat())) {
                FileUtils.deleteFolder(Paths.get(knowledge.getUrl()).toAbsolutePath().normalize().toFile());
            } else {
                FileUtils.deleteFile(Paths.get(knowledge.getUrl()).toAbsolutePath().normalize().toString());
            }
            deleteItem(knowledge.getId());
        }
        return Result.ok(fileName);
    }

    /**
     * 文件移动 on 2019/12/30 14:17
     *
     * @param parentId parentId
     * @param files    files
     * @return Result<?>
     */
    @Transactional(rollbackFor = Exception.class)
    public Result<?> move(Long parentId, List<StudyKnowledge> files) {
        StudyKnowledge knowledge = repositoryService.getStudyKnowledgeMapper().selectByPrimaryKey(parentId);
        if (knowledge == null) {
            return Result.body(null, ResultType.CHECK_ERROR).withMessage("该文件夹不存在");
        }
        if(knowledge.getUrl() == null || "".equals(knowledge.getUrl())){
            return Result.body(null, ResultType.CHECK_ERROR).withMessage("该文件夹不存在");
        }
        if (!"FO".equals(knowledge.getFormat())) {
            return Result.body(null, ResultType.CHECK_ERROR).withMessage("选中的不是文件夹");
        }
        for (StudyKnowledge value : files) {
            if(!knowledge.getType().equals(value.getType())){
                return Result.body(null, ResultType.CHECK_ERROR).withMessage("移动文件与父级类型不一致");
            }
            if (value.getId() == null || value.getId() <= 0) {
                return Result.body(null, ResultType.CHECK_ERROR).withMessage("文件id为空");
            }
            if (value.getUrl() == null || "".equals(value.getUrl())) {
                return Result.body(null, ResultType.CHECK_ERROR).withMessage("文件url为空");
            }
        }
        Account account = UserPrincipal.getCurrentUser();
        if(account == null || account.getId() == null){
            return Result.body(null, ResultType.CHECK_ERROR).withMessage("获取不到当前用户");
        }
        Path path = Paths.get(handleUrl(knowledge.getUrl())).toAbsolutePath().normalize();
        for (StudyKnowledge value : files) {
            File file = Paths.get(handleUrl(value.getUrl())).toAbsolutePath().normalize().toFile();
            Path newPath = path.resolve(file.getName());
            if (FileUtils.moveFile(file.getPath(), newPath.toString())) {
                int i = (value.getUrl().length() - value.getUrl().replace("/","").length()) + 1;
                value.setUrl(knowledge.getUrl() + "/" + file.getName());
                value.setParentId(knowledge.getId());
                value.setUpdater(account.getId());
                value.setUpdateBy(account.getRealName());
                value.setUpdateAt(new Date());
                repositoryService.getStudyKnowledgeMapper().updateByPrimaryKey(value);
                updateMove(value,account,i);
            }
        }
        return Result.ok(parentId);
    }

    public int updateMove(StudyKnowledge knowledge,Account account,int i){
        List<StudyKnowledge> list = repositoryService.getStudyKnowledgeMapper().getByparentid(knowledge.getId());
        if(list == null || list.size() <= 0){
            return 0;
        }
        for(StudyKnowledge value:list){
            String s = value.getUrl();
            for(int x = 0;x < i;x++){
                s = s.substring(s.indexOf("/") + 1);
            }
            value.setUrl(knowledge.getUrl() + "/" + s);
            value.setParentId(knowledge.getId());
            value.setUpdater(account.getId());
            value.setUpdateBy(account.getRealName());
            value.setUpdateAt(new Date());
            repositoryService.getStudyKnowledgeMapper().updateByPrimaryKey(value);
            updateMove(value,account,i + 1);
        }
        return 1;
    }

    @Transactional(rollbackFor = Exception.class)
    public TemFileResult manageFileUpload(MultipartFile file, String fileName, String targetDir, int sliceNum,
                                          boolean isLast, Long parentId, String classType, String originFileName) {
        TemFileResult result = fileService.storeFileBySlice(file, fileName, sliceNum, isLast,
                fileStorageProperties.getManageKnowledgeDir() + targetDir);
        String[] levels = targetDir.split("/");
        if (result.getComplete()) {
            StudyKnowledge knowledge = new StudyKnowledge(result.getFileType(), originFileName, file.getSize(), parentId,
                    levels.length, classType, result.getUrl());
            repositoryService.getStudyKnowledgeMapper().insert(knowledge);
        }
        return result;
    }

    @Transactional(rollbackFor = Exception.class)
    public Long createFolder(long parentId, String classType, String folderName) throws IOException {
        int level = 0;
        if (parentId != 0L) {
            StudyKnowledge parent = repositoryService.getStudyKnowledgeMapper().selectByPrimaryKey(parentId);
            level = parent.getLevel() + 1;
        }
        String url = "";
        if (classType.equals("MANAGE")) {
            url = fileStorageProperties.getManageKnowledgeDir();
        } else if (classType.equals("USER")) {
            url = fileStorageProperties.getUserKnowledgeDir();
        } else {
            throw new BusinessException("未找到适当的classType类型！");
        }
        Path targetPath = Paths.get(url + "/" + folderName).toAbsolutePath().normalize();
        Files.createDirectories(targetPath);
        for(String s:folderName.split("/")){
            url += "/" + s;
            StudyKnowledge knowledge = repositoryService.getStudyKnowledgeMapper().getByUrl(url.substring(2,url.length()));
            if(knowledge == null){
                knowledge = new StudyKnowledge("FO", s, 0, parentId, level, classType,url.substring(2,url.length()));
                repositoryService.getStudyKnowledgeMapper().insert(knowledge);
                level += 1;
            }else{
                level = knowledge.getLevel() + 1;
            }
            parentId = knowledge.getId();
        }
        return parentId;
    }

    /**
     * 文件下载 on 2019/12/30 17:33
     *
     * @param fileName fileName
     * @param request  request
     * @return ResponseEntity<?>
     */
    public ResponseEntity<?> download(String fileName, HttpServletRequest request) {
        List<StudyKnowledge> list = repositoryService.getStudyKnowledgeMapper().getByName(fileName);
        if (list == null || list.size() <= 0) {
            return ResponseEntity.ok(Result.body(null, ResultType.CHECK_ERROR).withMessage("该文件不存在"));
        }
        StudyKnowledge knowledge = list.get(0);
        UrlResource urlResource = null;
        String contentType = null;
        try {
            Path path = Paths.get(handleUrl(knowledge.getUrl())).toAbsolutePath().normalize();
            if("FO".equals(knowledge.getFormat())){
                File[] file = path.toFile().listFiles();
                String zipPath = path.toString();
                zipPath = zipPath.substring(0,zipPath.lastIndexOf(File.separator));
                zipPath = zipPath + File.separator + path.toFile().getName() + ".zip";
                urlResource = new UrlResource(new File(ZipUtils.zipFiles(file,zipPath,path.toFile().getName())).toURI());
            }else{
                urlResource = new UrlResource(path.toUri());
            }
            if (!urlResource.exists()) {
                return ResponseEntity.ok(Result.body(null, ResultType.CHECK_ERROR).withMessage("获取不到该文件"));
            }
            contentType = request.getServletContext().getMimeType(urlResource.getFile().getAbsolutePath());
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.ok(Result.body(null, ResultType.BUSINESS_SUCCESS));
        }
        if (contentType == null) {
            contentType = "application/octet-stream";
        }
        // 名字转换
        String[] strArr = urlResource.getFilename().split("\\.");
        String fileNamePrefix = strArr[0];
        String fileNameSuffix = strArr[1];
        String finalFileName = null;
        try {
            finalFileName = URLEncoder.encode(fileNamePrefix, "UTF-8") + "." + fileNameSuffix;
        } catch (UnsupportedEncodingException e) {
            System.out.println("文件名字转换异常");
            System.out.println(e.getMessage());
        }
        return ResponseEntity.ok().contentType(MediaType.parseMediaType(contentType))
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + finalFileName + "\"")
                .body(urlResource);
    }

    public Result<?> uploadFolder(MultipartFile file, String targetDir, Long parentId, String classType) throws IOException {
        StudyKnowledge knowledge = null;
        String url = "";
        if (classType.equals("MANAGE")) {
            url = fileStorageProperties.getManageKnowledgeDir();
        } else if (classType.equals("USER")) {
            url = fileStorageProperties.getUserKnowledgeDir();
        } else {
            throw new BusinessException("错误的ClassType");
        }
        String fileName = StringUtils.cleanPath(file.getOriginalFilename());
        knowledge = repositoryService.getStudyKnowledgeMapper().getByUrl(url + "/" + fileName);
        if(knowledge != null){
            return Result.ok(file.getOriginalFilename() + ",该文件已存在");
        }
        String filePathStr = "";
        if (classType.equals("MANAGE")) {
            filePathStr = fileService.storeFile(file, url);
        } else if (classType.equals("USER")) {
            filePathStr = fileService.storeFile(file, url);
        }
        StudyKnowledge studyKnowledge = new StudyKnowledge(filePathStr.substring(filePathStr.lastIndexOf(".") + 1,filePathStr.length()), file.getOriginalFilename(), file.getSize(), parentId,
                Paths.get(filePathStr).getNameCount(), classType, url + "/" + fileName);
        repositoryService.getStudyKnowledgeMapper().insert(studyKnowledge);
        return Result.ok(true);
    }

    /**
     * 处理url on 2020/1/13 15:00
     *
     * @param url url
     * @return String
     */
    private String handleUrl(String url){
        if("".equals(url) || url == null){
            return url;
        }
        String newUrl = "";
        if(url.charAt(0) == '.'){
            newUrl = url;
        }else if(url.charAt(0) == File.separator.toCharArray()[0]){
            newUrl = url;
        }else{
            newUrl = "." + File.separator + url;
        }
        return newUrl;
    }

    /**
     * 删除子级 on 2020/4/9 11:52
     *
     * @param id id
     * @return int
     */
    @Transactional(rollbackFor = Exception.class)
    public int deleteItem(Long id){
        repositoryService.getStudyKnowledgeMapper().deleteByPrimaryKey(id);
        List<StudyKnowledge> list = repositoryService.getStudyKnowledgeMapper().getByparentid(id);
        if(list == null || list.size() <= 0){
            return 0;
        }
        for(StudyKnowledge knowledge:list){
            deleteItem(knowledge.getId());
        }
        return 1;
    }

    /**
      * 检查文件格式 on 2022/2/24 10:04
      *
      * @param file file
      * @return Result<?>
      */
    public Result<?> checkFileType(MultipartFile file){
        if(file == null){
            return Result.body(null, ResultType.CHECK_ERROR).withMessage("文件为空");
        }
        if(file.getOriginalFilename() == null || "".equals(file.getOriginalFilename().trim())){
            return Result.body(null, ResultType.CHECK_ERROR).withMessage("文件名不正确");
        }
        String[] split = file.getOriginalFilename().split("\\.");
        if (split.length <= 1) {
            return Result.body(null, ResultType.CHECK_ERROR).withMessage("文件格式不正确");
        }
        String s = "jpg,gif,png,bmp,jpeg,doc,docx,ppt,pptx,xls,xlsx,pdf,mp4";
        String[] allowExtension = s.split(",");
        boolean b = Arrays.asList(allowExtension).contains(split[split.length - 1].toLowerCase());
        if(b){
            return Result.ok(b);
        }else{
            return Result.body(null, ResultType.CHECK_ERROR).withMessage("不支持该文件格式,支持的格式:" + s);
        }
    }
}
